import { SingletonBase } from "./SingletonBase";
import { Queue } from "../Utils/Queue";
import { resLoader } from "../res/ResLoader";

export class ResManager extends SingletonBase {

    //#region 循环加载资源
    private isLoading: boolean = false;//是否正在加载资源
    public loadResLoop() {
        if (this.isLoading) return;
        this.isLoading = true;
        let res = this.getLoadingResItem();
        if (!res) {
            this.isLoading = false;
            return;
        }
        let load_count: number = res.m_count;
        let queue: Queue<any> = new Queue<any>();
        if (this.getResPool(res.m_resName)) {
            queue = this.getResPool(res.m_resName).m_queue;
        }
        if (res.m_saveType == SaveType.UI||res.m_saveType == SaveType.Asset) {
            var pre = this.getUIRes(res.m_resName);
            if (pre) {
                let ret: RetHander = new RetHander();
                ret.m_arg = res.m_argArray;
                ret.m_data = [pre];
                ret.m_resName=res.m_resName;
                res.m_listener && res.m_listener(ret);
                this.isLoading = false;
                this.loadResLoop();
                return;
            }
        }
        else if (res.m_saveType == SaveType.Item) {
            let arr = this.getItemRes(res.m_resName, res.m_count);
            if (arr.length != 0) {
                let ret: RetHander = new RetHander();
                ret.m_arg = res.m_argArray;
                ret.m_data = arr;
                ret.m_resName=res.m_resName;
                res.m_listener && res.m_listener(ret);
                this.isLoading = false;
                this.loadResLoop();
                return;
            }
            load_count = res.m_count - queue.size();
        }

        let fun = function () {
            if (load_count > 0) {
                this._loadRes(res.m_resName, res.m_resType, function (ret: RetHander) {
                    if (!ret.m_err) {
                        res.m_prefab = ret.m_data;
                        ret.m_arg = res.m_argArray;
                        if (res.m_saveType == SaveType.Asset) {
                            ret.m_data = [ret.m_data];
                            ret.m_resName=res.m_resName;
                            res.m_listener && res.m_listener(ret);
                            setTimeout(function () {
                                this.isLoading = false;
                                this.loadResLoop();
                            }.bind(this), 1000 * 0.05);
                            return;
                        }
                        this.addResMap(res);
                        load_count--;
                        if (load_count <= 0) {
                            let arr = [];
                            if (res.m_saveType == SaveType.UI){
                                arr = [this.getUIRes(res.m_resName, res.m_count)];
                            }
                            else{
                                arr = this.getItemRes(res.m_resName, res.m_count);
                            }
                            ret.m_data = arr;
                            ret.m_arg = res.m_argArray;
                            ret.m_resName=res.m_resName;
                            res.m_listener && res.m_listener(ret);

                            setTimeout(function () {
                                this.isLoading = false;
                                this.loadResLoop();
                            }.bind(this), 1000 * 0.05);
                        }
                        else {
                            setTimeout(function () {
                                fun();
                            }.bind(this), 1000 * 0.05);
                        }
                    }
                    else {
                        res.m_listener && res.m_listener(ret);
                        setTimeout(function () {
                            this.isLoading = false;
                            this.loadResLoop();
                        }.bind(this), 1000 * 0.05);
                    }

                }.bind(this),res.m_onProgress);
            }
        }.bind(this);

        fun();
    }
    //#endregion

    //#region 加载队列
    private loadingResQueue = new Queue<LoadingResHander>();
    private get getResQueue(): Queue<LoadingResHander> {
        return this.loadingResQueue;
    }

    private getLoadingResItem(): LoadingResHander {
        return this.loadingResQueue.pop();
    }

    public loadRes(resName: string, resType: any, listener: Function, arg?: any) {
        let onProgress = null, count = 1, argArray = [], saveType = SaveType.UI;
        if (arg&&arg.onProgress)
            onProgress = arg.onProgress;
        if (arg&&arg.count)
            count = arg.count;
        if (arg&&arg.argArray)
            argArray = arg.argArray;
        if (arg&&arg.saveType)
            saveType = arg.saveType;

        this._addLoadingResItem(resName, resType, listener, onProgress, count, argArray, saveType);
    }
    private _addLoadingResItem(resName: string, resType: any, listener: Function,
        onProgress?: Function, count: number = 1, argArray: any[] = [], saveType: string = SaveType.UI) {
        let item: LoadingResHander = new LoadingResHander(resType, resName, count, listener, onProgress, argArray, saveType);
        this.loadingResQueue.push(item);
        this.loadResLoop();
        console.log(item);
    }
    //#endregion

    //#region  已经加载的资源 资源pool
    private resMap = new Map<string, PoolResHander>();
    private getResMap(): Map<string, PoolResHander> {
        return this.resMap;
    }
    private addResMap(res: LoadingResHander) {
        if(res.m_resType==cc.Prefab){
            let temp:any=cc.instantiate(res.m_prefab);
            this.resetResItem(res.m_resName, temp);
        }
        else{
            this.resetResItem(res.m_resName, res.m_prefab);
        }
    }
    public resetResItem(key: any, pre: any) {
        if (this.resMap.has(key) == false) {
            let _res: PoolResHander = new PoolResHander(key, pre);
            this.resMap.set(key, _res);
        }
        else {
            let _res: PoolResHander = this.getResPool(key);
            _res.push(pre);
        }
    }
    private hasRes(key: string): boolean {
        if (this.resMap.has(key)) {
            let _res: PoolResHander = this.getResPool(key);
            if (_res.m_queue.size() != 0)
                return true;
        }
        return false;
    }
    private getUIRes(key: string): any {
        if (this.hasRes(key)) {
            let _res: PoolResHander = this.getResPool(key);
            let temp: any = _res.m_queue.pop();
            _res.m_queue.push(temp);
            return temp;
        }
        return null;
    }
    private getResPool(key: string): PoolResHander {
        return this.resMap.get(key);
    }
    private getItemRes(key: string, count: number): any {
        if (this.hasRes(key)) {
            let _res: PoolResHander = this.getResPool(key);
            if (count <= _res.m_queue.size() && count != 0) {
                let arr: any[] = [];
                while (arr.length < count) {
                    arr.push(_res.m_queue.pop());
                }
                return arr;
            }
        }
        return [];
    }
    //#endregion

    //#region 加载资源
    private _loadRes(path: string, type: any, callback?: Function, onProgress?: Function) {
        let ret: RetHander = new RetHander();
        ret.m_type=type;
        if (path == '') {
            ret.m_err = '加载资源路径为空。'
            callback && callback(ret);
            return;
        }
        let temp = cc.loader.getRes(path);
        if (temp) {
            ret.m_data = temp;
            callback && callback(ret)
            return;
        }
        resLoader.loadRes(path,type,function (completedCount: number, totalCount: number, item: any) {
            onProgress && onProgress(completedCount, totalCount, item);
        },function (err,res) {
            if (err) {
                ret.m_err = err.message;
                callback && callback(ret);
                return;
            }
            ret.m_data=res;
            console.log(ret);
            callback && callback(ret);
            return;
        })
    }
    //#endregion
}

export class RetHander {
    public m_resName: string = '';//资源名称
    public m_info: string = '';//成功提示信息
    public m_err: string = '';//失败提示信息
    public m_data: any[] = [];//资源
    public m_arg: any[] = [];//参数列表
    public m_type:any;//资源类型
}

export enum SaveType{
    UI='UI',
    Item='Item',
    Asset='Asset'
}

export class LoadingResHander {
    public m_resType: any;//资源类型
    public m_resName: string = '';//资源名称
    public m_argArray: any[] = [];//加载参数
    public m_listener: Function = null;//回调
    public m_onProgress: Function = null;//进度回调
    public m_prefab: any;//资源
    public m_saveType: string;//保存类型
    public m_count: number;//加载个数
    constructor(resType: any, resName: string, count: number, listener: Function,
        onProgress?: Function, argArray: any[] = [], saveType: string = SaveType.UI) {
        this.m_resType = resType;
        this.m_resName = resName;
        this.m_listener = listener;
        this.m_argArray = argArray;
        this.m_saveType = saveType;
        this.m_count = count;
        this.m_onProgress = onProgress;
    }
}

export class PoolResHander {
    public m_name: string = '';//资源名称
    public m_queue: Queue<any> = new Queue<any>();//资源列表
    constructor(name: string, item?: any) {
        this.m_name = name;
        if(item)this.m_queue.push(item);
    }

    public push(item: any) {
        this.m_queue.push(item);
    }

    public pop(): any {
        return this.m_queue.pop();
    }
}
